package com.libmessagecenter

import android.content.Context
import android.content.Intent
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.libbase.Weak
import com.libbase.Wrapper
import com.libbase.extension.filterDuplicates
import com.libmessagecenter.models.Message
import com.libnetwork.Network
import com.libservice.ServiceManager
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.addTo
import io.reactivex.rxjava3.subjects.BehaviorSubject
import io.reactivex.rxjava3.subjects.PublishSubject
import java.util.Timer
import java.util.TimerTask

class LibMessageCenter {
    companion object {
        const val TAG = "LibMessageCenter"

        val instance: LibMessageCenter by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            LibMessageCenter()
        }
    }

    interface Adapter {
        fun didRegister(
            messageCenter: LibMessageCenter,
            deviceToken: String,
            completion: (result: Boolean) -> Unit
        )

        /* 重置推送未读数 */
        fun didClearAppIconBadgeNumber(
            messageCenter: LibMessageCenter,
            completion: (result: Boolean) -> Unit
        )

        /* 设置消息已读 */
        fun read(
            messageCenter: LibMessageCenter,
            messageIds: List<String>,
            completion: (unreadCount: Int?) -> Unit
        )

        /* 消息中心未读数 */
        fun getUnreadCount(messageCenter: LibMessageCenter, completion: (unreadCount: Int?) -> Unit)

        /* 重置消息中心未读数 */
        fun resetUnreadCount(messageCenter: LibMessageCenter, completion: (result: Boolean) -> Unit)
    }

    var compositeDisposable = CompositeDisposable()

    private var deviceToken: String? = null

    private val pushSDK: PushSDKInterface = PushSDK()

    @SuppressWarnings("unused")
    val messageWillPresent = PublishSubject.create<Message>()

    @SuppressWarnings("unused")
    val messageDidReceive = PublishSubject.create<Message>()

    val unreadCount = BehaviorSubject.createDefault(0)

    private var unreadCountTimer: Timer? = null

    var adapter: Adapter? by Weak({ null },
        willSet = null,
        didSet = {
            if (ServiceManager.instance.authService.authRepository.data != null) {
                startUnreadCountTimer()
            }
        })

    init {
        Network.instance
            .reachabilityListener
            .filterDuplicates(Network.instance.reachabilityListener.value as Network.NetworkReachabilityStatus)
            .subscribe({ networkReachabilityStatus ->
                if (!networkReachabilityStatus.isReachable) {
                    return@subscribe
                }

                deviceToken?.let { doRegister(it) }
            }, { error ->
                error.printStackTrace()
            })
            .addTo(compositeDisposable)

        ServiceManager.instance
            .authService
            .authRepository
            .dataObserver
            .filterDuplicates(Wrapper(ServiceManager.instance.authService.authRepository.data))
            .subscribe { element ->
                if (element.value != null) {
                    startUnreadCountTimer()
                } else {
                    unreadCount.onNext(0)
                    stopUnreadCountTimer()

                    clearAppIconBadgeNumber()
                }
            }
            .addTo(compositeDisposable)

        addLifecycleObserver()
    }

    fun register(context: Context, appId: String?, appKey: String?) {
        pushSDK.register(context, appId, appKey)
    }

    fun register(deviceToken: String) {
        this.deviceToken = deviceToken

        doRegister(deviceToken)
    }

    private fun doRegister(deviceToken: String) {
        adapter?.let { adapter ->
            adapter.didRegister(this, deviceToken) { result ->
                if (result) {
                    this.deviceToken = null
                }
            }
        }
    }

    fun handleIntent(intent: Intent): Boolean {
        return pushSDK.handleIntent(intent)
    }

    @Suppress("unused")
    fun onMessageWillPresent(message: Message) {
        messageWillPresent.onNext(message)

        getUnreadCount()
        clearAppIconBadgeNumber()
    }

    fun onMessageDidReceive(message: Message) {
        messageDidReceive.onNext(message)

        getUnreadCount()
        clearAppIconBadgeNumber()
    }

    fun clearAppIconBadgeNumber() {
        adapter?.didClearAppIconBadgeNumber(this) {
        }
    }

    fun read(messageIds: List<String>) {
        adapter?.read(this, messageIds) { unreadCount ->
            this.unreadCount.onNext(unreadCount ?: 0)
        }
    }

    fun getUnreadCount() {
        adapter?.getUnreadCount(this) { unreadCount ->
            this.unreadCount.onNext(unreadCount ?: 0)
        }
    }

    fun resetUnreadCount() {
        adapter?.resetUnreadCount(this) {
            unreadCount.onNext(0)
        }
    }

    private fun startUnreadCountTimer() {
        unreadCountTimer = Timer().apply {
            schedule(object : TimerTask() {
                override fun run() {
                    getUnreadCount()
                }
            }, 0, 1000 * 60)
        }
    }

    private fun stopUnreadCountTimer() {
        unreadCountTimer?.cancel()
        unreadCountTimer = null
    }

    private fun addLifecycleObserver() {
        ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onCreate(owner: LifecycleOwner) {
            }

            override fun onStart(owner: LifecycleOwner) {
                clearAppIconBadgeNumber()
            }

            override fun onStop(owner: LifecycleOwner) {
            }

            override fun onDestroy(owner: LifecycleOwner) {
            }
        })
    }
}